from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
import random
import string
from captcha.image import ImageCaptcha
from django.http import HttpResponse
import redis
from django.contrib.auth.hashers import check_password, make_password
from rest_framework_jwt.utils import jwt_payload_handler, jwt_encode_handler
from django.db.models import Q
from users.serializer import AddressSer
# Create your views here.

from users.models import Users, Addr


# 校验用户名
class CheckUser(APIView):
    def get(self, request, name):
        # 获取用户名的个数进行判断
        rest = Users.objects.filter(username=name).count()
        if rest > 0:
            return Response(
                {'msg': '用户名已经存在', 'code': 400}
            )
        return Response({'code': 200})


# 校验手机号
class CheckMobile(APIView):
    def get(self, request, mobile):
        # 获取手机号的个数进行判断
        rest = Users.objects.filter(mobile=mobile).count()
        if rest > 0:
            return Response(
                {'msg': '用户名已经存在', 'code': 400}
            )
        return Response({'code': 200})


# 生成图片验证码
class GenerateTu(APIView):
    def get(self, request, uuid):
        # 生成随机字符串
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 4))
        # 生成图片
        img = ImageCaptcha()
        # 把生成的字符串添加到图片上
        image = img.generate(salt)
        # 链接redis
        redis_cli = redis.Redis(host='127.0.0.1', port=6379)
        # 把字符串存入redis
        img_id = 'img_{}'.format(uuid)
        # 设置过期时间
        redis_cli.setex(img_id, 300, salt)
        # 返回图片
        return HttpResponse(image, content_type="image/png")


# 校验图片验证码
class CheckTu(APIView):
    def get(self, request):
        # 获取前端传递的数据
        img_id = request.query_params.get("imageCodeID")
        img_code = request.query_params.get("imageCode")
        # 链接redis
        redis_cli = redis.Redis(host='127.0.0.1', port=6379)
        # 获取出redis里的数据
        rest = redis_cli.get('img_{}'.format(img_id))
        # 判断取出来的数据
        if rest:
            # 用户输入的内容小写和图片的内容小写进行对比
            if rest.decode().lower() == img_code.lower():
                return Response({'code': 200})
            else:
                return Response({'msg': '验证码错误'})
        # 为取出 可能验证码过期
        else:
            return Response({'msg': '验证码以过期'})


# 注册
class Register(APIView):
    def post(self, request):
        # 获取前端传递的数据
        name = request.data.get("userName")
        pwd = request.data.get("pwd")
        mobile = request.data.get("mobile")
        agree = request.data.get("agree")
        # 判断转递的数据是否为空
        if not all([name, pwd, mobile]):
            return Response({'msg': '请输入完整的信息', 'code': 400})
        # 判断同意协议是否勾选
        if not agree:
            return Response({'msg': '请勾选同意协议', 'code': 400})
        # 存入数据库
        Users.objects.create_user(username=name, password=pwd, mobile=mobile)
        return Response({'msg': '注册成功', 'code': 200})


# 登录
class Login(APIView):
    def post(self, request):
        # 获取前端输入的用户名和密码
        user = request.data.get("user")
        pwd = request.data.get("pwd")
        # 判断用户是否存在
        try:
            name = Users.objects.get(Q(username=user) | Q(mobile=user))
        except Exception as e:
            print(e)
            return Response({'msg': '没有此用户，请先注册', 'code': 400})
        # 判断密码是否正确 把获取到的数据加密和数据库的密码比较
        is_correct = check_password(pwd, name.password)
        if is_correct:
            # 生成token
            payload = jwt_payload_handler(name)
            token = jwt_encode_handler(payload)
            # 把token写入cookie，便于退出
            rest = Response({'msg': '登录成功', 'code': 200, 'user': {'userName': name.username}, 'token': token})
            # 设置cookie中
            rest.set_cookie('token', token)
            return rest
        else:
            return Response({'msg': '用户名密码错误', 'code': 400})


# 退出登录
class TuiLogin(APIView):
    def post(self, request):
        token = request.COOKIES.get('token')
        if token:
            del token
        return Response({'msg': '退出成功', 'code': 200})


# 用户信息展示
class UserInfo(APIView):
    def post(self, request):
        name = request.data.get('user').get('userName')
        # 判断用户
        try:
            user = Users.objects.get(username=name)
        except Exception as e:
            print(e)
            return Response({'msg': '没有此用户', 'code': 400})
        # 返回用户信息
        addresses = user.addr_set.all()
        user_addr = []
        for addr in addresses:
            user_addr.append(AddressSer(addr).data)
        data = {
            "username": user.username,
            "phone": user.mobile,
            "addrs": user_addr
        }
        return Response({'msg': '获取用户信息成功', 'code': 200, 'userInfo': data})


# 添加收货地址
class AddAddress(APIView):
    def post(self, request):
        # 获取前端数据
        name = request.data.get('user').get('userName')
        receiver = request.data.get('receiver')
        receive_mobile = request.data.get('receive_mobile')
        receive_addr = request.data.get('receive_addr')
        is_default = request.data.get('is_default')
        try:
            user = Users.objects.get(username=name)
        except Exception as e:
            print(e)
            return Response({'msg': '此用户不存在', 'code': 400})
        # 添加的数据不能为空
        if not all([receiver, receive_mobile, receive_addr]):
            return Response({'msg': '请填写完整的信息', 'code': 400})
        add = Addr.objects.create(user_id=user.id, is_default=is_default, receive_addr=receive_addr,
                                  receive_mobile=receive_mobile, receiver=receiver)
        ser = AddressSer(add)
        return Response({'msg': '添加收货地址成功', 'code': 200, 'userInfo': ser.data})


# 修改用户信息
class UpDateUserInfo(APIView):
    def post(self, request):
        # 获取前端数据
        username = request.data.get("user").get("userName")
        mobile = request.data.get("phone")
        addrs = request.data.get("addrs")
        # 判断用户
        try:
            user = Users.objects.get(username=username)
        except Exception as e:
            print(e)
            return Response({'msg': "次用户不存在", "code": 400})
        # 判断手机号是否修改不等说明修改
        if user.mobile != mobile:
            # 判断手机号是否存在 存在就返回手机号存在
            if Users.objects.filter(mobile=mobile).count() > 0:
                return Response({'msg': '此手机号已经存在'})
            # 不存在就修改保存
            else:
                user.mobile = mobile
                user.save()
        # 查询地址
        print("1111>>>>", addrs)
        for addr_query_ser in addrs:
            # 更新
            addr = Addr.objects.get(id=addr_query_ser.get('id'))
            addr.receiver = addr_query_ser.get("receiver")
            addr.receive_mobile = addr_query_ser.get("receive_mobile")
            addr.receive_addr = addr_query_ser.get("receive_addr")
            addr.save()
        return Response({'msg': '更新信息成功', 'code': 200})


# 删除收货地址
class DeleteAddr(APIView):
    def post(self, request):
        # 获取前端传递的数据
        addr_id = request.data.get("addr_id")
        try:
            Addr.objects.get(id=addr_id).delete()
        except Exception as e:
            print(e)
            return Response({'msg': '地址不存在', 'code': 400})
        return Response({'msg': '删除成功', 'code': 200})


# 修改密码
class UpdatePwd(APIView):
    def post(self, request):
        # 获取前端传递的数据
        name = request.data.get('user')
        old_pwd = request.data.get('originPw')
        new_pwd = request.data.get('newPw')
        confirm_pwd = request.data.get('confirmNewPw')
        # 判断用户
        try:
            user = Users.objects.get(username=name)
        except Exception as e:
            print(e)
            return Response({'msg': '此用户不存在', 'code': 400})
        if not check_password(old_pwd, user.password):
            return Response({'msg': '原始密码不正确', 'code': 400})
        if new_pwd != confirm_pwd:
            return Response({'msg': '更新的两次密码不一致', 'code': 400})
        if old_pwd == new_pwd:
            return Response({'msg': '新旧密码一样，请重新输入', 'code': 400})
        user.password = make_password(new_pwd)
        user.save()
        return Response({'msg': '修改密码成功', 'code': 200})


